#include <cstring>
#include <string>
#include <iostream>

#include <fcntl.h>
#include <poll.h>
#include <sys/stat.h>
#include <unistd.h>

#include <iomuxhelper.hpp>

static int create_fifo(int argc, const char **argv)
{
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <filepath>" << std::endl;
        return 1;
    }

    for (int i = 1; i < argc; ++i) {
        const char *filepath = argv[i];
        if (mkfifo(filepath, 0666) == -1) {
            std::cerr << "Error creating named pipe: " << filepath << std::endl;
            return -1;
        }
    }

    return 0;
}

static int remove_fifo(int argc, const char **argv)
{
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <filepath>" << std::endl;
        return 1;
    }

    for (int i = 1; i < argc; ++i) {
        const char *filepath = argv[i];
        if (unlink(filepath) == -1) {
            std::cerr << "Error removing named pipe: " << filepath << std::endl;
            return -1;
        }
    }

    return 0;
}

static int do_read(int argc, const char **argv)
{
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <filepath>" << std::endl;
        return 1;
    }

    std::string filepath = std::string(argv[1]);

    FileDesc *fifo = new FileDesc(std::string(filepath), O_RDONLY);

    if (!fifo->is_readable()){
        std::cerr << "Error: no read permission" << std::endl;
        return -1;
    }

    do {
        std::string buf;
        buf = fifo->read();
        if (buf.empty()) {
            break;
        }

        std::cout << buf << std::endl;
    } while (true);

    delete fifo;

    return 0;
}

static int do_write(int argc, const char **argv)
{
    if (argc < 3) {
        std::cerr << "Usage: " << argv[0] << " <filepath> <mesg>" << std::endl;
        return 1;
    }

    std::string filepath = std::string(argv[1]);
    const char *msg = argv[2];
    FileDesc *fifo = new FileDesc(filepath, O_WRONLY);

    if (!fifo->is_writable()) {
        std::cerr << "Error: no write permission" << std::endl;
        return -1;
    }

    do {
        fifo->write(msg);
        std::cout << "Press enter to continue, q to exit" << std::endl;
        char input = std::cin.get(); // 等待用户按回车键
        if (input == 'q') {
            break;
        }
    } while (true);

    delete fifo;

    return 0;
}

struct cmd_desc {
    const char *name;
    const char *help;
    int (*func)(int argc, const char **argv);
};

static int print_help(int argc, const char **argv);

static const struct cmd_desc cmds[] = {
    {"help", "show help", print_help,},
    {"create", "", create_fifo,},
    {"remove", "", remove_fifo,},
    {"read", "read <filepath>", do_read,},
    {"write", "write <filepath> <msg>", do_write,},

    {NULL, NULL, NULL,},
};

static int print_help(int argc, const char **argv)
{
    const struct cmd_desc *desc;

    for (desc = cmds; desc->name; desc++) {
        printf("%s - %s\n", desc->name, desc->help);
    }

    return 0;
}

int main(int argc, const char **argv)
{

    if (argc < 2) {
        print_help(argc, argv);
        return 1;
    }

    const struct cmd_desc *desc;
    const char *cmd_name = argv[1];

    for (desc = cmds; desc->name; desc++) {
        if (strcmp(cmd_name, desc->name) == 0) {
            return desc->func(argc - 1, argv + 1);
        }
    }

    std::cerr << "Unknown command: " << cmd_name << std::endl;
    print_help(argc, argv);

    return 1;
}

